package showtime.framework.component.counter
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.ColorTransform;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.getTimer;
	
	/** 
	 * @project showtime
	 * @author yinhao
	 * @date 2011-5-24
	 *
	 */
	
	public class CoolingCounter extends Sprite
	{
		private const startFrom:Number = -90 / 180 * Math.PI;
		
		private var _running:Boolean = false;		
		private var _color:uint = 0;
		
		private var halfW:Number = 0;
		private var halfH:Number = 0;
		
		private var radianList:Array = null;
		private var pointXList:Array = null;
		private var pointYList:Array = null;
		
		private var beginTime:Number = 0;
		private var totalTime:Number = 0;
		
		private var maskShape:Shape = null;
		private var bitmap:Bitmap = null;
		
		public function CoolingCounter(target:DisplayObject)
		{
			mouseChildren = false;
			mouseEnabled = false;
			
			if (target)
			{
				setTarget(target);
			}
		}
		
		public function get running():Boolean
		{
			return _running;
		}
		
		public function get color():uint
		{
			return _color;
		}
		
		public function set color(value:uint):void
		{
			if (_color != value)
			{
				_color = value;
				
				if (bitmap)
				{
					var r:Number = (value & 0xFF0000) >>> 16;
					var g:Number = (value & 0x00FF00) >>> 8;
					var b:Number = value & 0x0000FF;
					
					bitmap.transform.colorTransform = new ColorTransform(0, 0, 0, 1, r, g, b);
				}
			}
		}
		
		public function dispose():void
		{
			try
			{
				bitmap.bitmapData.dispose();
				bitmap.bitmapData = null;
			}
			catch(e:Error)
			{
				
			}
			
			if (maskShape && maskShape.hasEventListener(Event.ENTER_FRAME))
			{
				maskShape.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
				maskShape.graphics.clear();
			}
		}
		
		public function setTarget(target:DisplayObject):void
		{
			if (!maskShape)
			{
				maskShape = new Shape();
				
				addChild(maskShape);
				
				if (!bitmap)
				{
					bitmap = new Bitmap();
				}
				
				if (bitmap.bitmapData)
				{
					bitmap.bitmapData.dispose();
				}
				
				var rect:Rectangle = target.getBounds(target.parent);
				
				halfW = rect.width  * 0.5;
				halfH = rect.height * 0.5;
				pointXList = [-halfW, -halfW, halfW, halfW];
				pointYList = [-halfH, halfH, halfH, -halfH];
				radianList = 
					[   Math.atan2(-halfH, -halfW) + Math.PI * 2,
						Math.atan2( halfH, -halfW),
						Math.atan2( halfH, halfW),
						Math.atan2( -halfH, halfW),
						startFrom 
					];
				
				var bitmapData:BitmapData = new BitmapData(rect.width, rect.height, true, 0x0);
				var stagePoint:Point = target.parent.localToGlobal(new Point(rect.x, rect.y));
				
				bitmapData.lock();
				for (var i:int = 0; i < rect.width; i++)
				{
					for (var j:int = 0; j < rect.height; j++)
					{
						if (target.hitTestPoint(stagePoint.x + i, stagePoint.y + j, true))
						{
							bitmapData.setPixel32(i, j, 0xFF000000);
						}
					
					}
				}
				
				bitmapData.unlock();
				bitmap.bitmapData = bitmapData;
				bitmap.x = -halfW;
				bitmap.y = -halfH;
				addChild(bitmap);
				bitmap.mask = maskShape;
				
				this.x = rect.x + halfW;
				this.y = rect.y + halfH;
			
				target.parent.addChildAt(this, target.parent.getChildIndex(target) + 1);
			}
		}
		
		public function start(totalTime:Number):void
		{
			if (maskShape)
			{
				this.totalTime = totalTime;
				beginTime = getTimer();
				_running = true;
				
			
				maskShape.graphics.beginFill(0);
				maskShape.graphics.drawRect( -halfW, -halfW, halfW * 2, halfH * 2);
				maskShape.graphics.endFill();
				
				if (!maskShape.hasEventListener(Event.ENTER_FRAME))
				{
					
					maskShape.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
				}
		
			}
		}
		
		private function enterFrameHandler(evt:Event):void 
		{
			var postTime:Number = getTimer() - beginTime;
			maskShape.graphics.clear();
			
			
			if (postTime >= totalTime)
			{
				maskShape.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
				_running = false;
				dispatchEvent(new Event(Event.COMPLETE));
			}
				
			else
			{
				maskShape.graphics.beginFill(0);
				maskShape.graphics.lineTo(0, -halfH);
				var currRadian:Number = 2 * Math.PI * (postTime / totalTime) + startFrom;
				
				var px:Number = 0;
				var py:Number = 0;
				
				for (var i:int = 0; i < 5; i++)
				{
					var radian:Number = radianList[i];
					if (currRadian < radian)
					{
						maskShape.graphics.lineTo(pointXList[i], pointYList[i]);
					}
					else
					{
						if (1 == i || 3 == i)
						{
							px = 1 == i ? -halfW : halfW;
							py = Math.tan(currRadian) * px;
						}
						else
						{
							py = 2 == i ? halfH : -halfH;
							px = py / Math.tan(currRadian);
						}
						
						maskShape.graphics.lineTo(px, py);
						break;
					}
				}
				
				maskShape.graphics.lineTo(0, 0);
				maskShape.graphics.endFill();
			}
		}
	}
}